// Creature behaviours
//--------------------------------
#ifndef BCREATURE_H
#define BCREATURE_H
#include "behaviour.h"

// Called to find a creature's sight range
// Param sightRange   - return value. A value of 0 is considered blind
// Param seeInDark    - whether this creature can see in the dark
// Param seeInvisible - whether this creature can see invisible
class BISight : public BIConst< int*, bool*, bool* > {
public:

    BEHAVIOUR_CALL const
    {
        return Sight( a0, a1, a2 );
    }

    BEHAVIOUR_START
    {
        *a0 = 128;
        *a1 = false;
        *a2 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Sight( int* sightRange, bool* seeInDark, bool* seeInvisible ) const = 0;

};

// Called to find a creature's skill level ~ unused
// Param skill       - the skill we wish to inquire about
// Param skillLevel  - return value for the skill level
class BISkills : public BIConst< int, int* > {
public:
    enum Skills {

    };

    BEHAVIOUR_CALL const
    {
        return Skills( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = 0;
    }
    BEHAVIOUR_END
    {
        *a1 = std::max( 0, *a1 );
    }

protected:

    virtual bool Skills( int skill, int* skillLevel ) const = 0;

};

// Called to find a creature's stats
// Params - return values for hpMax, mpMax, str, dex, int, ac, magicRes, fireRes
class BIStats : public BIConst< int*, int*, int*, int*, int*, int*, int*, int* > {
public:

    BEHAVIOUR_CALL const
    {
        return Stats( a0, a1, a2, a3, a4, a5, a6, a7 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0;
        *a1 = 0;
        *a2 = 0;
        *a3 = 0;
        *a4 = 0;
        *a5 = 0;
        *a6 = 0;
        *a7 = 0;
    }
    BEHAVIOUR_END
    {
        *a0 = std::min( 999, std::max( 0, *a0 ) );
        *a1 = std::min( 999, std::max( 0, *a1 ) );
        *a2 = std::min( 99, std::max( 0, *a2 ) );
        *a3 = std::min( 99, std::max( 0, *a3 ) );
        *a4 = std::min( 99, std::max( 0, *a4 ) );
        *a5 = std::min( 99, std::max( 0, *a5 ) );
        *a6 = std::min( 99, std::max( 0, *a6 ) );
        *a7 = std::min( 99, std::max( 0, *a7 ) );
    }

protected:

    virtual bool Stats( int* hpMax, int* mpMax, int* sStr, int* sDex, int* sInt,
                        int* ac, int* magicRes, int* fireRes ) const = 0;

};

// Called to find a creature's stats
// Params - return values for hpRegen, mpRegen, weightLimit
class BIDerivedStats : public BIConst< double*, double*, int* > {
public:

    BEHAVIOUR_CALL const
    {
        return DerivedStats( a0, a1, a2 );
    }

    BEHAVIOUR_START
    {
        *a0 = 0.0;
        *a1 = 0.0;
        *a2 = 0;
    }
    BEHAVIOUR_END
    {
        *a0 = std::max( 0.0, *a0 );
        *a1 = std::max( 0.0, *a1 );
        *a2 = std::min( 999 * 20, std::max( 0, *a2 ) );
    }

protected:

    virtual bool DerivedStats( double* hpRegen, double* mpRegen, int* weightMax ) const = 0;

};

// Called to list a creature's inventory
class BIInventory : public BI< ItemList* > {
public:

    BEHAVIOUR_CALL
    {
        return Inventory( a0 );
    }

    BEHAVIOUR_START
    {
        a0->clear();
    }
    BEHAVIOUR_END { }

protected:

    virtual bool Inventory( ItemList* list ) = 0;

};

// Called when a creature attempts to push an actor
// Param target  - target actor
// Param reverse - pull instead
// Param pushed  - whether pushthrough is allowed
class BIOnPush : public BI< Actor*, bool, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnPush( a0, a1, a2 );
    }

    BEHAVIOUR_START
    {
        *a2 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnPush( Actor* target, bool reverse, bool* pushed ) = 0;

};

// Called when a creature attempts to pick up an item
// Param item - item to pickup
// Param pickedUp - return value to indicate whether item was picked up
class BIOnPickup : public BI< Item**, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnPickup( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnPickup( Item** item, bool* pickedUp ) = 0;

};

// Called when a creature attempts to drop an item
// Param item - item to drop
// Param dropped - return value to indicate whether item was dropped
class BIOnDrop : public BI< Item**, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnDrop( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnDrop( Item** item, bool* dropped ) = 0;

};

// Called when a creature attempts to wear an item
// Param item - item to wear
// Param wieled - return value to indicate whether item was worn
class BIOnWear : public BI< Item**, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnWear( a0, a1 );
    }

    BEHAVIOUR_START { }
    BEHAVIOUR_END { }

protected:

    virtual bool OnWear( Item** item, bool* worn ) = 0;

};

// Called when a creature attempts to wield an item
// Param item - item to wield
// Param wieled - return value to indicate whether item was wieled
class BIOnWield : public BI< Item**, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnWield( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnWield( Item** item, bool* wielded ) = 0;

};

// Called when a creature attempts to remove an item
// Param item - item to remove
// Param wieled - return value to indicate whether item was removed
class BIOnRemove : public BI< Item**, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnRemove( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnRemove( Item** item, bool* removed ) = 0;

};

// Called when a creature attempts to eat an item
// Param item - item to eat
// Param eaten - return value to indicate whether item was eaten
class BIOnEat : public BI< Item**, bool* > {
public:

    BEHAVIOUR_CALL
    {
        return OnEat( a0, a1 );
    }

    BEHAVIOUR_START
    {
        *a1 = false;
    }
    BEHAVIOUR_END { }

protected:

    virtual bool OnEat( Item** item, bool* eaten ) = 0;

};

#endif
